
wbx.grid.body = (() => {
  // import
  let rawData, createDomByTagName, column, row;

  const state = {
    currentCell: null,
    isSelecting: false,
    rowStartIndex: 0,
    rowEndIndex: 0,
    columnStartIndex: 0,
    columnEndIndex: 0,
    isEditing: false // 是否有单元格在编辑
  };

  const dom = {
    cells: [],
    rows: [],
    columns: [],
    bodyWrapper: null
  };

  const setConfig = () => {
    rawData = wbx.model.getCellsData();
    createDomByTagName = wbx.util.createDomByTagName;
    column = wbx.model.column;
    row = wbx.model.row;
  };

  /**
   * 生成一个dom节点
   * @param {*} data 
   * @param {*} rowIndex 
   * @param {*} columnIndex 
   * @return dom
   */
  const createOneCell = (data, rowIndex, columnIndex) => {
    const cell = createDomByTagName('DIV');
    cell.classList.add('wbx-' + rowIndex + '-' + columnIndex);
    cell.classList.add('wbx-cell');

    cell.innerHTML = data[rowIndex][columnIndex];
    
    // add cell param
    cell.rowIndex = rowIndex;
    cell.columnIndex = columnIndex;

    // modify border collapse
    if (rowIndex === row.count - 1 ) {
      cell.classList.add('wbx-cell-last-row');
    }

    // 添加事件
    cell.onmouseenter = (e) => {
      if (state.isSelecting) {
        const target = e.target;
        console.log(`cell: ${target.rowIndex}-${target.columnIndex}`);
        selectCells(state.currentCell, target);
      }
    }

    cell.onmouseleave = (e) => {
      if (state.isSelecting) {
        unselectMulti();
      }
    };
    
    return cell;
  };

  const selectCells = (startCell, endCell) => {
    if (startCell.rowIndex < endCell.rowIndex) {
      state.rowStartIndex = startCell.rowIndex;
      state.rowEndIndex = endCell.rowIndex;
    } else {
      state.rowEndIndex = startCell.rowIndex;
      state.rowStartIndex = endCell.rowIndex;
    }
    if (startCell.columnIndex < endCell.columnIndex) {
      state.columnStartIndex = startCell.columnIndex;
      state.columnEndIndex = endCell.columnIndex;
    } else {
      state.columnEndIndex = startCell.columnIndex;
      state.columnStartIndex = endCell.columnIndex;
    }

    console.log(state.currentCell.columnIndex, state.currentCell.rowIndex);
    selectMulti();
  };

  const selectMulti = () => {
    // header
    wbx.grid.header.highlightColumnHeader(state.columnStartIndex, state.columnEndIndex);
    wbx.grid.header.highlightRowHeader(state.rowStartIndex, state.rowEndIndex);
    
    wbx.grid.setSelectedIndex(state.rowStartIndex, state.columnStartIndex,
      state.rowEndIndex, state.columnEndIndex);

    // body
    for (let i = state.rowStartIndex; i < state.rowEndIndex + 1; i++) {
      for (let j = state.columnStartIndex; j < state.columnEndIndex + 1; j++) {
        const cell = dom.cells[i][j];

        if ( i === state.rowStartIndex ) {
          cell.classList.add('multi-active-top');
        }
        if ( i === state.rowEndIndex ) {
          cell.classList.add('multi-active-bottom');
        }

        if ( j === state.columnStartIndex ) {
          cell.classList.add('multi-active-left');
        }
        if ( j === state.columnEndIndex ) {
          cell.classList.add('multi-active-right');
        }

        cell.classList.add('multi-active');
      }
    }
  };

  const render = (container) => {
    const gridBody = createDomByTagName('div');
    gridBody.classList.add('grid-body');

    gridBody.style.gridTemplateColumns = column.widths.join(' ');
    gridBody.style.gridTemplateRows = row.heights.join(' ');

    const cells = rawData.map((oneRow, rowIndex) => {
      return oneRow.map((oneRowColumn, columnIndex) => {
        // return rowIndex + ':' + columnIndex;
        return  createOneCell(rawData, rowIndex, columnIndex);
      })
    })

    console.log('cells data:\n', cells);

    dom.cells = cells;
    
    let currentCell = null;
    
    // reset
    dom.rows = [];
    dom.columns = [];

    for (let i = 0; i < row.count; i++ ) {
      // init row.cells
      if (typeof dom.rows[i] === 'undefined') {
        dom.rows[i] = cells[i];
      }
      for (let j = 0; j < column.count; j++ ) {
        currentCell = cells[i][j];
        // init column.cells
        if (typeof dom.columns[j] == 'undefined') {
          dom.columns[j] = [];
        }
        dom.columns[j].push(currentCell);
        gridBody.appendChild(currentCell);
      }
    }

    container.appendChild(gridBody);

    // add event listeners
    gridBody.onmousedown = onGridBodyMouseDown;
    gridBody.ondblclick = onGridBodyDblClick;
    document.onkeydown = (e) => {
      if (e.which === 13) {
        if (state.currentCell) {
          console.log(e.which);
          makeEditable(state.currentCell, false);
          // state.currentCell.setAttribute('contentEditable', false);
        }
      }
    };
    gridBody.onmousemove = onGridBodyMouseMove;
    gridBody.onmouseup = onGridBodyMouseUp;

    return gridBody;
  };

  // events
  const onGridBodyMouseMove = (e) => {
    if (state.isSelecting) {
    }
  };
  
  const onGridBodyMouseUp = (e) => {
    state.isSelecting = false;

  };

  const onGridBodyDblClick = (e) => {
    const target = e.target;
    if (target.classList.contains('wbx-cell')) {
      // 使之可编辑
      makeEditable(target, true);
    }
  };

  const makeEditable = (cell, enable) => {
    // state.currentCell = cell;
    if (enable) {
      cell.setAttribute('contentEditable', true);
      cell.focus();
      state.isEditing = true;
    } else {
      if (state.isEditing) {
        // save data
        // alert(cell.innerText);
        cell.setAttribute('contentEditable', false);
        console.log('saving------------' + cell.innerText);
        wbx.model.save(cell.innerText, cell.rowIndex, cell.columnIndex);
        state.isEditing = false;
      }
    }
  };

  const onGridBodyMouseDown = (e) => {
    wbx.grid.unselect();

    const target = e.target;

    if (target.classList.contains('wbx-cell')) {
      unselectBodyCell();
      selectBodyCell(target);
      state.isSelecting = true;
    }
  }

  const selectBodyCell = (cell) => {
    if (state.currentCell && state.currentCell !== cell && state.isEditing) {
      makeEditable(state.currentCell, false);
    }
    cell.classList.add('active');
    
    // 高亮header
    if (state.currentCell) {
      wbx.grid.header.unselectRow(state.currentCell.rowIndex);
      wbx.grid.header.unselectColumn(state.currentCell.columnIndex);
    }
    
    wbx.grid.header.highlightColumnHeader(cell.columnIndex);
    wbx.grid.header.highlightRowHeader(cell.rowIndex);
    
    wbx.grid.setSelectedIndex(cell.rowIndex, cell.columnIndex);

    state.currentCell = cell;
  }

  const unselectMulti = () => {
    // body
    for (let i = state.rowStartIndex; i < state.rowEndIndex + 1; i++) {
      for (let j = state.columnStartIndex; j < state.columnEndIndex + 1; j++) {
        const cell = dom.cells[i] ? dom.cells[i][j] : null;
        if (cell) {
          cell.classList.remove('multi-active');
          cell.classList.remove('multi-active-top');
          cell.classList.remove('multi-active-left');
          cell.classList.remove('multi-active-right');
          cell.classList.remove('multi-active-bottom');
        }
      }
    }

    // header
    wbx.grid.unselectHeader();
  };

  const unselectBodyCell = () => {
    if (state.currentCell) {
      state.currentCell.classList.remove('active');
    }

    unselectMulti();
  }
  
  const init = (container) => {
    console.log('wbx.grid.body init');

    setConfig();

    // dom.cells = render(container);
    dom.bodyWrapper = render(container);

    // addEventListeners();
  };

  const reRender = (container) => {
    dom.bodyWrapper = render(container);
  };
  
  const remove = () => {
    dom.bodyWrapper.remove();
  }

  const resizeRows = () => {
    dom.bodyWrapper.style.gridTemplateRows = row.heights.join(' ');
  };
  
  const resizeColumns = () => {
    dom.bodyWrapper.style.gridTemplateColumns = column.widths.join(' ');
  }

  const highlightColumn = (index) => {
    dom.columns[index].forEach(cell => {
      cell.classList.add('column-active');
    });
  };

  const highlightRow = (index) => {
    dom.rows[index].forEach(cell => {
      cell.classList.add('row-active');
    });
  };

  const unselectRow = (index) => {
    // unselect body cell
    if (dom.rows[index]) {
      dom.rows[index].forEach(cell => {
        cell.classList.remove('row-active');
      });
    }
  };

  const unselectColumn = (index) => {
    // unselect body cell
    if (dom.columns[index]) {
      dom.columns[index].forEach(cell => {
        cell.classList.remove('column-active');
      });
    }
  };

  return {
    init: init,
    resizeRows: resizeRows,
    resizeColumns: resizeColumns,
    highlightColumn: highlightColumn,
    highlightRow: highlightRow,
    unselectColumn: unselectColumn,
    unselectRow: unselectRow,
    reRender: reRender,
    remove: remove,
    unselectBodyCell: unselectBodyCell
  };

})();